<?php
declare(strict_types=1);

namespace App\Service;

use App\Model\Dao\ChannelCollectionConnDao;
use App\Model\Dao\ChannelCollectionDao;
use App\Model\Dao\ChannelInfoDao;
use App\Model\Dao\ChannelMchConnDao;
use App\Utils\CustomUtils;
use App\Utils\StringUtils;
use Hyperf\Database\Query\Builder;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use App\Model\Dao\ChannelCollectionMchConnDao;
use App\Exception\XZXValidationException;
use App\Constants\XZXResponseCode;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Coroutine;
use App\Utils\DateUtils;
use Hyperf\Utils\Arr;

class ChannelCollectionMchConnService {

    /**
     * @Inject()
     * @var ChannelCollectionMchConnDao
     */
    private $ChannelCollectionMchConnDao;

    /**
     * @Inject()
     * @var ChannelCollectionConnDao
     */
    private $ChannelCollectionConnDao;

    /**
     * @Inject()
     * @var ChannelCollectionDao
     */
    private $ChannelCollectionDao;

    /**
     * @Inject()
     * @var ChannelMchConnDao
     */
    private $ChannelMchConnDao;

    /**
     * @Inject()
     * @var ChannelInfoDao
     */
    private $ChannelInfoDao;

    /**
     * @Inject()
     * @var RiskSyncService
     */
    private $RiskSyncService;

    /**
     * 列表
     *
     * @param array $param
     *
     * @return array
     */
    public function list (array $param) {

        $limit = $param['limit'];
        $page  = $param['page'];

        $total = $this->ChannelCollectionMchConnDao->getCount($param);
        $list  = $this->ChannelCollectionMchConnDao->getList($param, $page, $limit);

        $list = CustomUtils::formatCreateTime($list);

        $data = [
            'total' => $total,
            'list'  => $list,
        ];

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $data);
    }

    /**
     * 列表
     *
     * @param array $param
     *
     * @return array
     */
    public function channelList (array $param) {

        $limit = $param['limit'];
        $page  = $param['page'];

        $total = $this->ChannelCollectionMchConnDao->getCount($param);
        $list  = $this->ChannelCollectionMchConnDao->getChannelList($param, $page, $limit);

        $data = [
            'total' => $total,
            'list'  => $list,
        ];

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $data);
    }

    /**
     * 设置商户-通道集合关联
     * @param $params
     *
     * @return array
     * @throws \Throwable
     */
    public function setBind ($params) {

        $params = Arr::only($params, [
            'mchNo',
            'payType',
            'collectionId',
            'createBy',
            'updateBy',
        ]);

        $mchNo        = $params['mchNo'];
        $payType      = $params['payType'];
        $collectionId = $params['collectionId'];

        if (!is_null($collectionId)) {
            // 检查通道集合是否存在
            $collection = $this->ChannelCollectionDao->getWhere([
                'id'      => $collectionId,
                'payType' => $payType,
            ]);

            if (!$collection) {
                throw new \Exception('通道集合不存在');
            }
        }

        Db::beginTransaction();

        try {

            // 按照支付类型解除关联, 因为商户通道集合关联里, 按照商户-支付类型唯一
            $this->ChannelCollectionMchConnDao->delWhere([
                'mchNo'   => $mchNo,
                'payType' => $payType,
            ]);

            if (!is_null($collectionId)) {

                // 关联当前的
                $update            = $params;
                $update['payType'] = $payType;
                $update['id']      = StringUtils::uuidV4();

                $this->ChannelCollectionMchConnDao->insert($update);

                // 补充商户-通道限额记录
                $this->_appendMchChannelConn($mchNo, $collectionId, $params);
            }

            // 通知刷新风控缓存
            $this->RiskSyncService->syncChannelCollectionMchRef($mchNo);

        } catch (\Throwable $e) {
            Db::rollBack();
            throw $e;
        }

        Db::commit();

        $data = [];

        return CustomUtils::buildSuccess($data);
    }

    /**
     * 补充商户-通道限额记录
     * @param $mchNo
     * @param $collectionId
     * @param $params
     *
     * @return bool
     */
    protected function _appendMchChannelConn ($mchNo, $collectionId, $params) {

        // 获取该集合关联的通道
        $connList      = $this->ChannelCollectionConnDao->getWhereList(['collectionId' => $collectionId]);
        $channelIdList = array_column($connList, 'channelId');

        // 空集合, 无需操作
        if (empty($channelIdList))
            return false;

        $channelList = $this->ChannelInfoDao->getWhereList(function (Builder $q) use ($channelIdList) {
            $q->whereIn('id', $channelIdList);
        });

        $channelNoList = array_column($channelList, 'channelNo');

        // 空集合, 无需操作
        if (empty($channelNoList))
            return false;


        // 找出商户-通道限额表中没有记录的channelNo
        $limitList           = $this->ChannelMchConnDao->getWhereList(function (Builder $q) use ($mchNo, $channelNoList) {
            $q->where('mchNo', $mchNo);
            $q->whereIn('channelNo', $channelNoList);
        });
        $channelNoListExist  = array_column($limitList, 'channelNo');
        $channelNoListAppend = array_diff($channelNoList, $channelNoListExist);

        if (empty($channelNoListAppend))
            return false;

        // 批量插入
        $insertList = [];
        foreach ($channelNoListAppend as $channelNo) {
            array_push($insertList, [
                'id'        => StringUtils::uuidV4(),
                'mchNo'     => $mchNo,
                'channelNo' => $channelNo,
                'createBy'  => $params['createBy'],
                'updateBy'  => $params['updateBy'],
            ]);
        }

        $this->ChannelMchConnDao->insert($insertList);

        return true;
    }

    /**
     * 解除关联
     *
     * @param $params
     *
     * @return array
     * @throws \Exception
     */
    public function setUnbind ($params) {

        $mchNo        = $params['mchNo'];
        $collectionId = $params['collectionId'];

        // 解除关联
        $this->ChannelCollectionMchConnDao->delWhere([
            'mchNo'        => $mchNo,
            'collectionId' => $collectionId,
        ]);

        $data = [];

        return CustomUtils::buildSuccess($data);
    }

}
